 
  

 






<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 
<html>

<!-- Mirrored from www.javapractices.com/topic/TopicAction.do;jsessionid=4FCCB481C702D708A7360133D128E359?Id=233 by HTTrack Website Copier/3.x [XR&CO'2010], Sun, 12 Jun 2011 17:27:18 GMT -->
<!-- Added by HTTrack --><meta http-equiv="content-type" content="text/html;charset=UTF-8"><!-- /Added by HTTrack -->
<head>
 <title>
  Java Practices -> Verify input with Model Objects
 </title>
 <link rel="stylesheet" type="text/css" href="../stylesheet8.css" media="all">
 
 <link rel="shortcut icon" href='../images/favicon.ico' type="image/vnd.microsoft.icon">
 <meta name="description" content="Concise presentations of java programming practices, tasks, and conventions, amply illustrated with syntax highlighted code examples.">
 
 <meta name='keywords' content='java,java programming,java practices,java idiom,java style,java design patterns,java coding conventions,'>
 
 
</head>
 
<body>


<div class='menu-bar'>
 
  <a href='../home/HomeAction.html' title='Table of Contents'>Home</a> |
  <a href='../vote/VoteSummaryAction-2.html' title='View Poll Results'>Poll</a> |
   
  <A href='../feedback/FeedbackAction451f-2.html?Operation=Show' title='Send Your Feedback'>Wiki</a> |
  <b><a href='../source/SourceAction-2.html' title='Grab Source Code'>Source Code</a></b><IMG class='no-margin' SRC="../images/goldstar.gif" ALT=""> |

  <a href='http://www.web4j.com/Java_Web_Application_Framework_Overview.jsp?From=1' title='Free Download - Java Web Application Framework'><b>WEB4J</b></a> |
  
  <a href='http://www.date4j.net/' title='Replacement for java.util.Date'><b>DATE4J</b></a> |

   <a href='../references/ReferencesAction-2.html' title='References'>Links</a>
   
  <form action='http://www.javapractices.com/search/SearchAction.do' method='get' class='search-form'>
   <input type='text' name='SearchTerms' value="" size=12 maxlength=50 class='search'>
   <input type='submit' value="Search">
  </form>
 
</div>

<P>



  

 






<p class="display-messages">

 

 

</p>


<div class="main-layout">
 
   

 




<div class='page-title'>Verify input with Model Objects</div>

<div class='main-body'>
 
<br>
Validation of user input is important for almost all applications. 
There seems to be two places where you may implement such validation logic
<ul>
 <li>directly in the view-related classes
 <li>not in the view, but in your Model Object instead
</ul>

<P>Implementing validation in the Model Object has some strong advantages :
<ul>
 <li>the Model Object is the <a href='TopicAction0ec8-2.html?Id=209'>natural home for such logic</a>
 <li>since the code is not tied to the GUI, it is much simpler to test using tools such as <a href='TopicActiond5a5-2.html?Id=33'>JUnit</a>
 <li>complex validations that depend on more than one input item are handled just as easily as any other validation
</ul>

<P><b>Example</b>

<P>Here is a Model Object class named Movie. 
It performs all its validation in its constructors.
If a problem occurs, a checked exception named InvalidUserInput is thrown.
<br>
<PRE>

<span class='keyword'>package</span> hirondelle.movies.edit;

<span class='keyword'>import</span> java.math.BigDecimal;
<span class='keyword'>import</span> java.util.*;

<span class='keyword'>import</span> hirondelle.movies.exception.InvalidInputException;
<span class='keyword'>import</span> hirondelle.movies.util.Util;

<span class='comment'>/**
 Data-centric class encapsulating all fields related to movies. 
 
 &lt;P&gt;This class exists  in order to encapsulate, validate, and sort movie information.
  This class is used both to validate user input, and act as a 'transfer object' when 
  interacting with the database.
 
  &lt;P&gt;&lt;b&gt;This class would greatly benefit from a JUnit test class, to test its data 
  validation and sorting.&lt;/b&gt;
*/</span>
<span class='keyword'>final</span> <span class='keyword'>class</span> Movie <span class='keyword'>implements</span> Comparable&lt;Movie&gt;{

  <span class='comment'>/**
   Constructor taking regular Java objects natural to the domain.
   
   &lt;P&gt;When the user has entered text, this constructor is called indirectly, through 
   {@link #Movie(String, String, String, String, String)}.
   
   @param aId optional, the database identifer for the movie. This item is optional since, 
   for 'add' operations,  it has yet to be assigned by the database.
   @param aTitle has content, name of the movie
   @param aDateViewed optional, date the movie was screened by the user
   @param aRating optional, in range 0.0 to 10.0
   @param aComment optional, any comment on the movie
  */</span>
  Movie(
    String aId, String aTitle, Date aDateViewed, BigDecimal aRating, String aComment
  ) <span class='keyword'>throws</span> InvalidInputException {
    fId = aId;
    fTitle = aTitle;
    fDateViewed = aDateViewed;
    fRating = aRating;
    fComment = aComment;
    validateState();
  }
  
  <span class='comment'>/**
   Constructor which takes all parameters as &lt;em&gt;text&lt;/em&gt;.
   
   &lt;P&gt;Raw user input is usually in the form of &lt;em&gt;text&lt;/em&gt;.
   This constructor &lt;em&gt;first&lt;/em&gt; parses such text into the required 'base objects' - 
   {@link Date}, {@link BigDecimal} and so on. If those parse operations &lt;em&gt;fail&lt;/em&gt;, 
   then the user is shown an error message. If N such errors are present in user input, 
   then  N &lt;em&gt;separate&lt;/em&gt; message will be presented for each failure, one by one.
   
   &lt;P&gt;If all such parse operations &lt;em&gt;succeed&lt;/em&gt;, then the "regular" constructor 
   {@link #Movie(String, String, Date, BigDecimal, String)}
   will then be called. It's important to note that this call to the second constructor 
   can in turn result in &lt;em&gt;another&lt;/em&gt; error message being shown to the 
   user (just one this time). 
 */</span>
  Movie(
    String aId, String aTitle, String aDateViewed, String aRating, String aComment
  ) <span class='keyword'>throws</span> InvalidInputException {
      <span class='keyword'>this</span>(
        aId, aTitle, Util.parseDate(aDateViewed, <span class='literal'>"Date Viewed"</span>), 
        Util.parseBigDecimal(aRating, <span class='literal'>"Rating"</span>), aComment
      );
  }
  
  String getId(){ <span class='keyword'>return</span> fId; }
  
  <span class='comment'>/**
   This set method is rather artificial. It results from the toy persistence layer. 
   It's dissatisfying to add this method since the class would otherwise be immutable. 
   Immutability is a highly desirable characteristic.
  */</span>
  <span class='keyword'>void</span> setId(String aId){  fId = aId; }
  
  String getTitle(){ <span class='keyword'>return</span> fTitle; }
  Date getDateViewed(){ <span class='keyword'>return</span> fDateViewed; }
  BigDecimal getRating(){ <span class='keyword'>return</span> fRating; }
  String getComment(){ <span class='keyword'>return</span> fComment; }
  
  <span class='keyword'>@Override</span> <span class='keyword'>public</span> <span class='keyword'>boolean</span> equals(Object aThat){
    <span class='keyword'>if</span> ( <span class='keyword'>this</span> == aThat ) <span class='keyword'>return</span> <span class='keyword'>true</span>;
    <span class='keyword'>if</span> ( !(aThat <span class='keyword'>instanceof</span> Movie) ) <span class='keyword'>return</span> <span class='keyword'>false</span>;
    Movie that = (Movie)aThat;
    <span class='keyword'>return</span> 
      areEqual(<span class='keyword'>this</span>.fTitle, that.fTitle) &amp;&amp; 
      areEqual(<span class='keyword'>this</span>.fDateViewed, that.fDateViewed) &amp;&amp; 
      areEqual(<span class='keyword'>this</span>.fRating, that.fRating) &amp;&amp; 
      areEqual(<span class='keyword'>this</span>.fComment, that.fComment)
    ; 
  }
  
  <span class='keyword'>@Override</span> <span class='keyword'>public</span> <span class='keyword'>int</span> hashCode(){
    <span class='keyword'>int</span> result = <span class='literal'>17</span>;
    result = addHash(result, fTitle);
    result = addHash(result, fDateViewed);
    result = addHash(result, fRating);
    result = addHash(result, fComment);
    <span class='keyword'>return</span> result;
  }
  
  <span class='keyword'>@Override</span> <span class='keyword'>public</span> String toString(){
    <span class='keyword'>return</span> 
      <span class='literal'>"Movie  Id:"</span> + fId + <span class='literal'>" Title:"</span> + fTitle + <span class='literal'>" Date Viewed:"</span> + fDateViewed + 
      <span class='literal'>" Rating:"</span> + fRating + <span class='literal'>" Comment: "</span> + fComment
    ; 
  }
  
  <span class='comment'>/** 
   Default sort by Date Viewed, then Title. 
   Dates have the most recent items listed first. 
 */</span>
  <span class='keyword'>public</span> <span class='keyword'>int</span> compareTo(Movie aThat) {
    <span class='keyword'>if</span> ( <span class='keyword'>this</span> == aThat ) <span class='keyword'>return</span> EQUAL;
   
    <span class='keyword'>int</span> comparison = DESCENDING*comparePossiblyNull(<span class='keyword'>this</span>.fDateViewed, aThat.fDateViewed);
    <span class='keyword'>if</span> ( comparison != EQUAL ) <span class='keyword'>return</span> comparison;
    
    comparison = <span class='keyword'>this</span>.fTitle.compareTo(aThat.fTitle);
    <span class='keyword'>if</span> ( comparison != EQUAL ) <span class='keyword'>return</span> comparison;
    
    comparison = comparePossiblyNull(<span class='keyword'>this</span>.fRating, aThat.fRating);
    <span class='keyword'>if</span> ( comparison != EQUAL ) <span class='keyword'>return</span> comparison;
   
    comparison = comparePossiblyNull(<span class='keyword'>this</span>.fComment, aThat.fComment);
    <span class='keyword'>if</span> ( comparison != EQUAL ) <span class='keyword'>return</span> comparison;
    
    <span class='keyword'>return</span> EQUAL;
  }
  
  <span class='comment'>/** Sort by Title. */</span>
  <span class='keyword'>static</span> Comparator&lt;Movie&gt; TITLE_SORT = <span class='keyword'>new</span> Comparator&lt;Movie&gt;(){
    <span class='keyword'>public</span> <span class='keyword'>int</span> compare(Movie aThis, Movie aThat) {
      <span class='keyword'>if</span> ( aThis == aThat ) <span class='keyword'>return</span> EQUAL;

      <span class='keyword'>int</span> comparison = aThis.fTitle.compareTo(aThat.fTitle);
      <span class='keyword'>if</span> ( comparison != EQUAL ) <span class='keyword'>return</span> comparison;
      
      comparison = DESCENDING*comparePossiblyNull(aThis.fDateViewed, aThat.fDateViewed);
      <span class='keyword'>if</span> ( comparison != EQUAL ) <span class='keyword'>return</span> comparison;
      
      comparison = comparePossiblyNull(aThis.fRating, aThat.fRating);
      <span class='keyword'>if</span> ( comparison != EQUAL ) <span class='keyword'>return</span> comparison;
     
      comparison = comparePossiblyNull(aThis.fComment, aThat.fComment);
      <span class='keyword'>if</span> ( comparison != EQUAL ) <span class='keyword'>return</span> comparison;
      
      <span class='keyword'>return</span> EQUAL;
    };
  };
  
  <span class='comment'>/** Sort by Rating (descending), then Date Viewed (descending). */</span>
  <span class='keyword'>static</span> Comparator&lt;Movie&gt; RATING_SORT = <span class='keyword'>new</span> Comparator&lt;Movie&gt;(){
    <span class='keyword'>public</span> <span class='keyword'>int</span> compare(Movie aThis, Movie aThat) {
      <span class='keyword'>if</span> ( aThis == aThat ) <span class='keyword'>return</span> EQUAL;

      <span class='keyword'>int</span> comparison = DESCENDING*comparePossiblyNull(aThis.fRating, aThat.fRating);
      <span class='keyword'>if</span> ( comparison != EQUAL ) <span class='keyword'>return</span> comparison;

      comparison = DESCENDING*comparePossiblyNull(aThis.fDateViewed, aThat.fDateViewed);
      <span class='keyword'>if</span> ( comparison != EQUAL ) <span class='keyword'>return</span> comparison;
      
      comparison = aThis.fTitle.compareTo(aThat.fTitle);
      <span class='keyword'>if</span> ( comparison != EQUAL ) <span class='keyword'>return</span> comparison;
      
      comparison = comparePossiblyNull(aThis.fComment, aThat.fComment);
      <span class='keyword'>if</span> ( comparison != EQUAL ) <span class='keyword'>return</span> comparison;
      
      <span class='keyword'>return</span> EQUAL;
    };
  };
  
  <span class='comment'>/** Sort by Comment. */</span>
  <span class='keyword'>static</span> Comparator&lt;Movie&gt; COMMENT_SORT = <span class='keyword'>new</span> Comparator&lt;Movie&gt;(){
    <span class='keyword'>public</span> <span class='keyword'>int</span> compare(Movie aThis, Movie aThat) {
      <span class='keyword'>if</span> ( aThis == aThat ) <span class='keyword'>return</span> EQUAL;

      <span class='keyword'>int</span> comparison = comparePossiblyNull(aThis.fComment, aThat.fComment);
      <span class='keyword'>if</span> ( comparison != EQUAL ) <span class='keyword'>return</span> comparison;
      
      comparison = aThis.fTitle.compareTo(aThat.fTitle);
      <span class='keyword'>if</span> ( comparison != EQUAL ) <span class='keyword'>return</span> comparison;
      
      comparison = comparePossiblyNull(aThis.fRating, aThat.fRating);
      <span class='keyword'>if</span> ( comparison != EQUAL ) <span class='keyword'>return</span> comparison;

      comparison = DESCENDING*comparePossiblyNull(aThis.fDateViewed, aThat.fDateViewed);
      <span class='keyword'>if</span> ( comparison != EQUAL ) <span class='keyword'>return</span> comparison;
      
      <span class='keyword'>return</span> EQUAL;
    };
  };
  
  <span class='comment'>// PRIVATE //
</span>  <span class='keyword'>private</span> String fId;
  <span class='keyword'>private</span> <span class='keyword'>final</span> String fTitle;
  <span class='keyword'>private</span> <span class='keyword'>final</span> Date fDateViewed;
  <span class='keyword'>private</span> <span class='keyword'>final</span> BigDecimal fRating;
  <span class='keyword'>private</span> <span class='keyword'>final</span> String fComment;
  <span class='keyword'>private</span> <span class='keyword'>static</span> <span class='keyword'>final</span> BigDecimal TEN = <span class='keyword'>new</span> BigDecimal(<span class='literal'>"10.0"</span>);
  <span class='keyword'>private</span> <span class='keyword'>static</span> <span class='keyword'>final</span> <span class='keyword'>int</span> EQUAL = <span class='literal'>0</span>;
  <span class='keyword'>private</span> <span class='keyword'>static</span> <span class='keyword'>final</span> <span class='keyword'>int</span> DESCENDING = -<span class='literal'>1</span>;
  
  <span class='keyword'>private</span> <span class='keyword'>void</span> validateState() <span class='keyword'>throws</span> InvalidInputException {
    InvalidInputException ex = <span class='keyword'>new</span> InvalidInputException();
    
    <span class='keyword'>if</span>( ! Util.textHasContent(fTitle) ) {
      ex.add(<span class='literal'>"Title must have content"</span>);
    }
    <span class='keyword'>if</span> ( fRating != <span class='keyword'>null</span> ){
      <span class='keyword'>if</span> ( fRating.compareTo(BigDecimal.ZERO) &lt; <span class='literal'>0</span> ) {
        ex.add(<span class='literal'>"Rating cannot be less than 0."</span>);
      }
      <span class='keyword'>if</span> ( fRating.compareTo(TEN) &gt; <span class='literal'>0</span> ) {
        ex.add(<span class='literal'>"Rating cannot be greater than 10."</span>);
      }
    }
    <span class='keyword'>if</span> ( ex.hasErrors() ) {
      <span class='keyword'>throw</span> ex;
    }
  }
  
  <span class='keyword'>private</span> <span class='keyword'>boolean</span> areEqual(Object aThis, Object aThat){
    <span class='keyword'>return</span> aThis == <span class='keyword'>null</span> ? aThat == <span class='keyword'>null</span> : aThis.equals(aThat);
  }
  
  <span class='keyword'>private</span> <span class='keyword'>int</span> addHash(<span class='keyword'>int</span> aHash, Object aField){
    <span class='keyword'>int</span> result = <span class='literal'>37</span>*aHash;
    <span class='keyword'>if</span> (aField != <span class='keyword'>null</span>){
      result = result + aField.hashCode();
    }
    <span class='keyword'>return</span> result;
  }
  
  <span class='comment'>/** Utility method.  */</span>
  <span class='keyword'>private</span> <span class='keyword'>static</span> &lt;T <span class='keyword'>extends</span> Comparable&lt;T&gt;&gt; <span class='keyword'>int</span> comparePossiblyNull(T aThis, T aThat){
    <span class='keyword'>int</span> result = EQUAL;
    <span class='keyword'>int</span> BEFORE = -<span class='literal'>1</span>;
    <span class='keyword'>int</span> AFTER = <span class='literal'>1</span>;
    
    <span class='keyword'>if</span>(aThis != <span class='keyword'>null</span> &amp;&amp; aThat != <span class='keyword'>null</span>){ 
      result = aThis.compareTo(aThat);
    }
    <span class='keyword'>else</span> {
      <span class='comment'>//at least one reference is null - special handling
</span>      <span class='keyword'>if</span>(aThis == <span class='keyword'>null</span> &amp;&amp; aThat == <span class='keyword'>null</span>) {
        <span class='comment'>//do nothing - they are not distinct 
</span>      }
      <span class='keyword'>else</span> <span class='keyword'>if</span>(aThis == <span class='keyword'>null</span> &amp;&amp; aThat != <span class='keyword'>null</span>) {
        result = BEFORE;
      }
      <span class='keyword'>else</span> <span class='keyword'>if</span>( aThis != <span class='keyword'>null</span> &amp;&amp; aThat == <span class='keyword'>null</span>) {
        result = AFTER;
      }
    }
    <span class='keyword'>return</span> result;
  }
} 
</PRE>
<br>

The user edits Movie data using a dialog (not listed here). 
When the user hits a button, execution passes to the following MovieController class. 
The <tt>actionPerformed</tt> method first attempts to build a Movie object from user input. 
If a problem is detected, then an error message is displayed to the user. 
<br>
<PRE>

<span class='keyword'>package</span> hirondelle.movies.edit;

<span class='keyword'>import</span> hirondelle.movies.exception.InvalidInputException;
<span class='keyword'>import</span> hirondelle.movies.main.MainWindow;
<span class='keyword'>import</span> hirondelle.movies.util.Edit;
<span class='keyword'>import</span> hirondelle.movies.util.Util;

<span class='keyword'>import</span> java.awt.event.ActionEvent;
<span class='keyword'>import</span> java.awt.event.ActionListener;
<span class='keyword'>import</span> java.util.logging.Logger;

<span class='keyword'>import</span> javax.swing.JOptionPane;

<span class='comment'>/**
 Add a new {@link Movie} to the database, or change an existing one. 
 
 &lt;P&gt;It's important to note that this class uses most of the other classes in 
 this feature to get its job done (it doesn't use the &lt;tt&gt;Action&lt;/tt&gt; classes):
 &lt;ul&gt;
   &lt;li&gt;it gets user input from the view - {@link MovieView}
   &lt;li&gt;it validates user input using the model - {@link Movie}
   &lt;li&gt;it persists the data using the Data Access Object  - {@link MovieDAO}
 &lt;/ul&gt;
*/</span>
<span class='keyword'>final</span> <span class='keyword'>class</span> MovieController <span class='keyword'>implements</span> ActionListener {
  
  <span class='comment'>/**
   Constructor.
   @param aView user interface
   @param aEdit identifies what type of edit - add or change 
  */</span>
  MovieController(MovieView aView, Edit aEdit){
    fView = aView;
    fEdit = aEdit;
  }
  
  <span class='comment'>/**
   Attempt to add a new {@link Movie}, or edit an existing one.
   
   &lt;P&gt;If the input is invalid, then inform the user of the problem(s).
   If the input is valid, then add or change the &lt;tt&gt;Movie&lt;/tt&gt;, close the dialog, 
   and update the main window's display.  
  */</span>
  <span class='keyword'>public</span> <span class='keyword'>void</span> actionPerformed(ActionEvent aEvent){
    fLogger.fine(<span class='literal'>"Editing movie"</span> + fView.getTitle());
    <span class='keyword'>try</span> {
      createValidMovieFromUserInput();
    }
    <span class='keyword'>catch</span>(InvalidInputException ex){
      informUserOfProblems(ex);
    }
    <span class='keyword'>if</span> ( isUserInputValid() ){
      <span class='keyword'>if</span>( Edit.ADD == fEdit ) {
        fLogger.fine(<span class='literal'>"Add operation."</span>);
        fDAO.add(fMovie);
      }
      <span class='keyword'>else</span> <span class='keyword'>if</span> (Edit.CHANGE == fEdit) {
        fLogger.fine(<span class='literal'>"Change operation."</span>);
        fDAO.change(fMovie);
      }
      <span class='keyword'>else</span> {
        <span class='keyword'>throw</span> <span class='keyword'>new</span> AssertionError();
      }
      fView.closeDialog();
      MainWindow.getInstance().refreshView();
    }
  }

  <span class='comment'>// PRIVATE //
</span>  <span class='keyword'>private</span> <span class='keyword'>final</span> MovieView fView;
  <span class='keyword'>private</span> Movie fMovie;
  <span class='keyword'>private</span> Edit fEdit;
  <span class='keyword'>private</span> MovieDAO fDAO = <span class='keyword'>new</span> MovieDAO();
  <span class='keyword'>private</span> <span class='keyword'>static</span> <span class='keyword'>final</span> Logger fLogger = Util.getLogger(MovieController.<span class='keyword'>class</span>);
  
  <span class='keyword'>private</span> <span class='keyword'>void</span> createValidMovieFromUserInput() <span class='keyword'>throws</span> InvalidInputException {
    fMovie = <span class='keyword'>new</span> Movie(
      fView.getId(), fView.getTitle(), fView.getDateViewed(), 
      fView.getRating(), fView.getComment()
    );
  }

  <span class='keyword'>private</span> <span class='keyword'>boolean</span> isUserInputValid(){
    <span class='keyword'>return</span> fMovie != <span class='keyword'>null</span>;
  }
  
  <span class='keyword'>private</span> <span class='keyword'>void</span> informUserOfProblems(InvalidInputException aException) {
    Object[] messages = aException.getErrorMessages().toArray();
    JOptionPane.showMessageDialog(
      fView.getDialog(), messages, 
      <span class='literal'>"Movie cannot be added"</span>, JOptionPane.ERROR_MESSAGE
    );
  }
} 
</PRE>
<br>
<br>
<br>

</div>




<div class='topic-section'>See Also :</div>
<div class='main-body'>
 
  
  <a href='TopicActiond838-2.html?Id=29'>Immutable objects</a> <br>
 
  
  <a href='TopicActiond5a5-2.html?Id=33'>Use a testing framework (JUnit)</a> <br>
 
  
  <a href='TopicActioncded-2.html?Id=151'>Verify input with regular expressions</a> <br>
 
  
  <a href='TopicAction11fc-2.html?Id=167'>Input dialogs</a> <br>
 
  
  <a href='TopicAction0ec8-2.html?Id=209'>Validation belongs in a Model Object</a> <br>
 
</div>


<div class='topic-section'>Would you use this technique?</div>
<div class='main-body'>
  
  <form action="http://www.javapractices.com/vote/AddVoteAction.do" method='post'>
    Yes<input type='radio' name='Choice' value='Y' >
    &nbsp;&nbsp;No<input type='radio' name='Choice' value='N'>
    &nbsp;&nbsp;Undecided<input type='radio' name='Choice' value="?" >
    &nbsp;&nbsp;<input type=submit value="Vote" >
    <input type='hidden' name='Operation' value='Apply'>
    <input type='hidden' name='TopicId' value='233'>
  </form>
</div>

<div style='height:10.0em;'></div>

 
 
</div>

  

 





<div align='center' class='legalese'>  
&copy; 2011 Hirondelle Systems |
<a href='../source/SourceAction-2.html'><b>Source Code</b></a><IMG class='no-margin' SRC="../images/goldstar.gif" ALT=""> |
<a href="mailto:webmaster@javapractices.com">Contact</a> |
<a href="http://creativecommons.org/licenses/by-nc-sa/1.0/">License</a> |
<a href='../apps/cjp.rss'>RSS</a>
<!-- ukey="2AC36CD2" -->
<!-- ckey="16DF3D87" -->
<br>

 Individual code snippets can be used under this <a href='../LICENSE.txt'>BSD license</a> - Last updated on June 6, 2010.<br>
 Over 150,000 unique IPs last month - <span title='Java Practices 2.6.5, Mon May 16 00:00:00 EDT 2011'>Built with</span> <a href='http://www.web4j.com/'>WEB4J</a>.<br>
 - In Memoriam : Bill Dirani -
</div>

<script src="../../www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-2633428-1";
urchinTracker();
</script>



</body>

<!-- Mirrored from www.javapractices.com/topic/TopicAction.do;jsessionid=4FCCB481C702D708A7360133D128E359?Id=233 by HTTrack Website Copier/3.x [XR&CO'2010], Sun, 12 Jun 2011 17:27:18 GMT -->
<!-- Added by HTTrack --><meta http-equiv="content-type" content="text/html;charset=UTF-8"><!-- /Added by HTTrack -->
</html>
